AK、SK实现(双方API交互:签名及验证)

您所在的位置:网站首页 Sk telecom认证 AK、SK实现(双方API交互:签名及验证)

AK、SK实现(双方API交互:签名及验证)

#AK、SK实现(双方API交互:签名及验证)| 来源: 网络整理| 查看: 265

参考:https://blog.csdn.net/yqwang75457/article/details/117815474

1、原理

AK/SK: AK:Access Key Id,用于标示用户。 SK:Secret Access Key,是用户用于加密认证字符串和用来验证认证字符串的密钥,其中SK必须保密。 通过使用Access Key Id / Secret Access Key加密的方法来验证某个请求的发送者身份。

基本思路: 1.客户端需要在认证服务器中预先设置 access key(AK 或叫 app ID) 和 secure key(SK)。 2.在调用 API 时,客户端需要对参数和 access key 等信息结合 secure key 进行签名生成一个额外的 sign字符串。 3.服务器接收到用户的请求后,系统将使用AK对应的相同的SK和同样的认证机制生成认证字符串,并与用户请求中包含的认证字符串进行比对。如果认证字符串相同,系统认为用户拥有指定的操作权限,并执行相关操作;如果认证字符串不同,系统将忽略该操作并返回错误码。

2、实现 2.1 服务端

注解拦截器,拦截请求

@Documented @Retention(RetentionPolicy.RUNTIME) @Target({ElementType.METHOD,ElementType.TYPE}) public @interface IdentifySk { String value() default ""; }

切面

@Component @Aspect public class IdentifyRequest { @Pointcut("@annotation(com.chinatower.platform.client.aop.IdentifySk)") public void pointCut() { } @Before(value = "pointCut()") public void before(JoinPoint joinPoint) { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); HttpServletRequest request = attributes.getRequest(); //获取请求头信息 String ts = request.getHeader("ts"); Long timeStamp = StrUtil.isNotBlank(ts) ? Long.valueOf(ts) : null; String msgId = request.getHeader("msgId"); String appId = request.getHeader("appId"); String sign = request.getHeader("sign"); boolean res = SignUtil.checkHeaderInfo(timeStamp, msgId, appId, sign); Validate.isTrue(res,"请求失败,请检查请求头"); } }

生成sign加密工具类

@Slf4j public class SHACoderUtil { public static String sha256(String str){ String encodeStr = ""; try { MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); messageDigest.update(str.getBytes("UTF-8")); encodeStr = byte2Hex(messageDigest.digest()); } catch (Exception e) { log.error("sha256加码失败",e); } return encodeStr; } /** * 将byte转为16进制 * @param bytes * @return */ private static String byte2Hex(byte[] bytes){ StringBuffer stringBuffer = new StringBuffer(); String temp = null; for (int i=0;i 20 * 60 * 1000) { return false; } //根据参数加密,验证和传来的sign是否一致 String reSign = getSign(appId, CommonConstant.SK, String.valueOf(ts), msgId); if (sign.equals(reSign)) { return true; } return false; } }

使用注解

@IdentifySk() @PostMapping("/testSk") public void testSk() { System.out.println("ceshi"); } 2.2 客户端

加密工具类,同上SHACoderUtil 生成请求头和sign工具类

public class SignUtil { /** * 构建请求头 调用方 */ public static Map requestHeader(String appId, String appSecret) { String ts = String.valueOf(System.currentTimeMillis()); String msgId = UUID.randomUUID().toString(); Map header = new HashMap(16); // 进行接口调用时的时间戳,即当前时间戳(毫秒),服务端会校验时间戳,例如时间差超过20分钟则认为请求无效,防止重复请求的攻击 header.put("ts", ts); //每个请求提供一个唯一的标识符,服务器能够防止请求被多次使用 header.put("msgId", msgId); header.put("appId", appId); String sign = getSign(appId, appSecret, ts, msgId); header.put("sign", sign); return header; } /** * 按签名算法获取sign(客户端和服务器端算法一致,都需要用) * * @param appId * @param appSecret * @param ts 时间戳 * @param msgId 请求唯一标识 * @return */ public static String getSign(String appId, String appSecret, String ts, String msgId) { String str = IStringUtils.spliceStr("ts=", ts, "&msgId=", msgId, "&appId=", appId, "&appSecret=", appSecret); // 对待加密字符串进行加密,得到sign值 return SHACoderUtil.sha256(str); } }

远程请求http工具类

@Slf4j public class HttpClientUtil { private static final String ENCODING_TYPE = "UTF-8"; public static String doGet(String url, Map param) { log.info("doGet方法,url={}, param={}", url, param); CloseableHttpClient httpclient = HttpClients.createDefault(); String resultString = ""; CloseableHttpResponse response = null; try { // 创建uri URIBuilder builder = new URIBuilder(url); if (param != null) { for (String key : param.keySet()) { builder.addParameter(key, param.get(key)); } } URI uri = builder.build(); HttpGet httpGet = new HttpGet(uri); response = httpclient.execute(httpGet); // 判断返回状态是否为200 if (response.getStatusLine().getStatusCode() == 200) { resultString = EntityUtils.toString(response.getEntity(), ENCODING_TYPE); } log.info("doGet方法返回状态={}, 结果={}", response.getStatusLine().getStatusCode(), resultString); } catch (Exception e) { log.error("发送get请求失败,原因={}", e.getLocalizedMessage()); e.printStackTrace(); } finally { try { if (response != null) { response.close(); } httpclient.close(); } catch (IOException e) { log.error("关闭流失败,原因={}", e.getMessage()); e.printStackTrace(); } } return resultString; } public static String doPostJson(String url, String json,Integer timeOut) { log.info("Http 的请求地址是{}, 请求参数是 {}",url,json); CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { HttpPost httpPost = new HttpPost(url); // 创建请求内容 StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); //构建超时等配置信息 RequestConfig config = RequestConfig.custom().setConnectTimeout(timeOut) //连接超时时间 .setConnectionRequestTimeout(timeOut) //从连接池中取的连接的最长时间 .setSocketTimeout(timeOut) //数据传输的超时时间 .setStaleConnectionCheckEnabled(true) //提交请求前测试连接是否可用 .build(); httpPost.setConfig(config); response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), ENCODING_TYPE); } catch (ConnectTimeoutException e){ // 链接拒绝 ConnectTimeoutException log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("连接超时", CommonConstant.HTTP_OUT_TIME); } catch (HttpHostConnectException e){ // 链接拒绝 ConnectTimeoutException log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("连接拒绝", CommonConstant.HTTP_OUT_TIME); } catch (SocketTimeoutException e){ // 链接超时 log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("请求超时",CommonConstant.HTTP_OUT_TIME); } catch (Exception e) { // 其他异常 log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("请求失败",CommonConstant.HTTP_OUT_TIME_ERROR); } finally { try { if (response != null) { response.close(); } } catch (IOException e) { log.error("关闭流失败, 原因={}", e.getMessage()); e.printStackTrace(); } } log.info("Http 请求结果是{}",resultString); return resultString; } /** * 带请求头的的post请求 * @param url * @param headMap * @param json * @param timeOut * @return */ public static String doPostJson(String url, Map headMap,String json,Integer timeOut) { log.info("Http 的请求地址是{},请求头:{}, 请求参数是 {}",url, JSON.toJSONString(headMap),json); CloseableHttpClient httpClient = HttpClients.createDefault(); CloseableHttpResponse response = null; String resultString = ""; try { HttpPost httpPost = new HttpPost(url); //请求头 if (headMap != null && !headMap.isEmpty()){ for (String key:headMap.keySet()){ httpPost.addHeader(key,headMap.get(key)); } } // 创建请求内容 if (StrUtil.isNotBlank(json)){ StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON); httpPost.setEntity(entity); } //构建超时等配置信息 RequestConfig config = RequestConfig.custom().setConnectTimeout(timeOut) //连接超时时间 .setConnectionRequestTimeout(timeOut) //从连接池中取的连接的最长时间 .setSocketTimeout(timeOut) //数据传输的超时时间 .setStaleConnectionCheckEnabled(true) //提交请求前测试连接是否可用 .build(); httpPost.setConfig(config); response = httpClient.execute(httpPost); resultString = EntityUtils.toString(response.getEntity(), ENCODING_TYPE); } catch (ConnectTimeoutException e){ // 链接拒绝 ConnectTimeoutException log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("连接超时", CommonConstant.HTTP_OUT_TIME); } catch (HttpHostConnectException e){ // 链接拒绝 ConnectTimeoutException log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("连接拒绝",CommonConstant.HTTP_OUT_TIME); } catch (SocketTimeoutException e){ // 链接超时 log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("请求超时",CommonConstant.HTTP_OUT_TIME); } catch (Exception e) { // 其他异常 log.error("发送post json 请求失败,原因={}", e); resultString = httpTimeOutOrConnect("请求失败",CommonConstant.HTTP_OUT_TIME_ERROR); } finally { try { if (response != null) { response.close(); } } catch (IOException e) { log.error("关闭流失败, 原因={}", e.getMessage()); e.printStackTrace(); } } log.info("Http 请求结果是{}",resultString); return resultString; } /** * * @return */ private static String httpTimeOutOrConnect(String returnMsg, String returnCode){ JSONObject jsonObject = new JSONObject(); jsonObject.put("returnMsg", returnMsg); jsonObject.put("returnCode", returnCode); jsonObject.put("errorMsg", returnMsg); jsonObject.put("errorCode", returnCode); return jsonObject.toJSONString(); } }

测试请求服务端:

main(){ Map headMap = SignUtil.requestHeader(commonProperties.getAk(), commonProperties.getSk()); HttpClientUtil.doPostJson(url, headMap, "ceshi", 60000); }


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3